
<!DOCTYPE html>
<html lang="en">
    <head>

    <title>ILRuntime中的反射 — ILRuntime</title>
    <meta charset="utf-8">
    <meta name="description" content="ILRuntime">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

    <link rel="stylesheet" href="/ILRuntime/public/css/page.css">

    <script src="/ILRuntime/public/js/vue.js"></script>
    <script src="/ILRuntime/public/js/jquery.js"></script>
    </head>

    <body>
        
            <nav class="nav">
    <div class="border">
        <img src="/ILRuntime/public/images/logo.png" />
        <button class="hiden-in-phone">V1.4</button>
        <button id="btn-menu" class="hiden-in-pc">菜单</button>
        <ul class="nav-link hiden-in-phone">
            <!--li>
                <form id="search-form">
                    <input type="text" id="search-query" class="search-query">
                </form>
            </li!-->
            <li><a href="https://github.com/Ourpalm/ILRuntime" class="nav-link-li">下载项目</a></li>
            <li><a href="/ILRuntime/public/v1/guide/version.html" class="nav-link-li">更新记录</a></li>
            <li><a href="/ILRuntime/public/v1/guide/contribution.html" class="nav-link-li">贡献指南</li>
            <li><a href="/ILRuntime/public/v1/guide/index.html" class="nav-link-li">教程</a></li>
            <li><a href="/ILRuntime/public/" class="nav-link-li current">首页</a></li>
        </ul>
    </div>
</nav>

<div id="container" class="container clear">
    <section class="sidebar clearfix">
    <ul>
        
            
            
                <li><h3>基础</h3></li>
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/index.html" class="sidebar-link">介绍</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/version.html" class="sidebar-link">更新记录</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/contribution.html" class="sidebar-link">贡献指南</a></p>
            </li>
        
            
            
            
                <li><h3>教程</h3></li>
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/tutorial.html" class="sidebar-link">从零开始</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/delegate.html" class="sidebar-link">ILRuntime中使用委托</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/cross-domain.html" class="sidebar-link">ILRuntime中跨域继承</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/reflection.html" class="sidebar-link current">ILRuntime中的反射</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/redirection.html" class="sidebar-link">CLR重定向</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/bind.html" class="sidebar-link">CLR绑定</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/litjson.html" class="sidebar-link">LitJson集成</a></p>
            </li>
        
            
            
            
            
                <li><h3>其他</h3></li>
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/il2cpp.html" class="sidebar-link">IL2CPP打包注意事项</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/performance-optimization.html" class="sidebar-link">ILRuntime的性能优化</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/principle.html" class="sidebar-link">ILRuntime的实现原理</a></p>
            </li>
        
    </ul>
</section>
    <article class="clearfix">
    <h2 id="ILRuntime中的反射"><a href="#ILRuntime中的反射" class="headerlink" title="ILRuntime中的反射"></a>ILRuntime中的反射</h2><p>用C#开发项目，很多时候会需要使用反射来实现某些功能。但是在脚本中使用反射其实是一个非常困难的事情。因为这需要把ILRuntime中的类型转换成一个真实的C#运行时类型，并把它们映射起来</p>
<p>默认情况下，System.Reflection命名空间中的方法，并不可能得知ILRuntime中定义的类型，因此无法通过Type.GetType等接口取得热更DLL里面的类型。而且ILRuntime里的类型也并不是一个System.Type。</p>
<p>为了解决这个问题，ILRuntime额外实现了几个用于反射的辅助类：<code>ILRuntimeType</code>，<code>ILRuntimeMethodInfo</code>，<code>ILRuntimeFieldInfo</code>等，来模拟系统的类型来提供部分反射功能</p>
<h3 id="通过反射获取Type"><a href="#通过反射获取Type" class="headerlink" title="通过反射获取Type"></a>通过反射获取Type</h3><p>在<code>热更DLL</code>当中，直接调用Type.GetType(“TypeName”)或者typeof(TypeName)均可以得到有效System.Type类型实例<br><figure class="highlight csharp"><table><tr><td class="code"><pre><span class="line"><span class="comment">//在热更DLL中，以下两种方式均可以</span></span><br><span class="line">Type t = <span class="keyword">typeof</span>(TypeName);</span><br><span class="line">Type t2 = Type.GetType(<span class="string">"TypeName"</span>);</span><br></pre></td></tr></table></figure></p>
<p>在<code>Unity主工程中</code>，无法通过Type.GetType来取得热更DLL内部定义的类，而只能通过以下方式得到System.Type实例：</p>
<figure class="highlight csharp"><table><tr><td class="code"><pre><span class="line">IType type = appdomain.LoadedTypes[<span class="string">"TypeName"</span>];</span><br><span class="line">Type t = type.ReflectedType;</span><br></pre></td></tr></table></figure>
<h3 id="通过反射创建实例"><a href="#通过反射创建实例" class="headerlink" title="通过反射创建实例"></a>通过反射创建实例</h3><p>在<code>热更DLL</code>当中，可以直接通过Activator来创建实例：</p>
<figure class="highlight csharp"><table><tr><td class="code"><pre><span class="line">Type t = Type.GetType(<span class="string">"TypeName"</span>);<span class="comment">//或者typeof(TypeName)</span></span><br><span class="line"><span class="comment">//以下两种方式均可以</span></span><br><span class="line"><span class="keyword">object</span> instance = Activator.CreateInstance(t);</span><br><span class="line"><span class="keyword">object</span> instance = Activator.CreateInstance&lt;TypeName&gt;();</span><br></pre></td></tr></table></figure>
<p>在<code>Unity主工程中</code>，无法通过Activator来创建热更DLL内类型的实例，必须通过AppDomain来创建实例：<br><figure class="highlight csharp"><table><tr><td class="code"><pre><span class="line"><span class="keyword">object</span> instance = appdomain.Instantiate(<span class="string">"TypeName"</span>);</span><br></pre></td></tr></table></figure></p>
<h3 id="通过反射调用方法"><a href="#通过反射调用方法" class="headerlink" title="通过反射调用方法"></a>通过反射调用方法</h3><p>在<code>热更DLL</code>当中，通过反射调用方法跟通常C#用法没有任何区别</p>
<figure class="highlight csharp"><table><tr><td class="code"><pre><span class="line">Type type = <span class="keyword">typeof</span>(TypeName);</span><br><span class="line"><span class="keyword">object</span> instance = Activator.CreateInstance(type);</span><br><span class="line">MethodInfo mi = type.GetMethod(<span class="string">"foo"</span>);</span><br><span class="line">mi.Invoke(instance, <span class="literal">null</span>);</span><br></pre></td></tr></table></figure>
<p>在<code>Unity主工程中</code>，可以通过C#通常用法来调用，也可以通过ILRuntime自己的接口来调用，两个方式是等效的：<br><figure class="highlight csharp"><table><tr><td class="code"><pre><span class="line">IType t = appdomain.LoadedTypes[<span class="string">"TypeName"</span>];</span><br><span class="line">Type type = t.ReflectedType;</span><br><span class="line"></span><br><span class="line"><span class="keyword">object</span> instance = appdomain.Instantiate(<span class="string">"TypeName"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//系统反射接口</span></span><br><span class="line">MethodInfo mi = type.GetMethod(<span class="string">"foo"</span>);</span><br><span class="line">mi.Invoke(instance, <span class="literal">null</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//ILRuntime的接口</span></span><br><span class="line">IMethod m = t.GetMethod(<span class="string">"foo"</span>, <span class="number">0</span>);</span><br><span class="line">appdomain.Invoke(m, instance, <span class="literal">null</span>);</span><br></pre></td></tr></table></figure></p>
<h3 id="通过反射获取和设置Field的值"><a href="#通过反射获取和设置Field的值" class="headerlink" title="通过反射获取和设置Field的值"></a>通过反射获取和设置Field的值</h3><p>在热更DLL和Unity主工程中获取和设置Field的值跟通常C#用法没有区别<br><figure class="highlight csharp"><table><tr><td class="code"><pre><span class="line">Type t;</span><br><span class="line">FieldInfo fi = t.GetField(<span class="string">"field"</span>);</span><br><span class="line"><span class="keyword">object</span> val = fi.GetValue(instance);</span><br><span class="line">fi.SetValue(instance, val);</span><br></pre></td></tr></table></figure></p>
<h3 id="通过反射获取Attribute标注"><a href="#通过反射获取Attribute标注" class="headerlink" title="通过反射获取Attribute标注"></a>通过反射获取Attribute标注</h3><p>在热更DLL和Unity主工程中获取Attribute标注跟通常C#用法没有区别<br><figure class="highlight csharp"><table><tr><td class="code"><pre><span class="line">Type t;</span><br><span class="line">FieldInfo fi = t.GetField(<span class="string">"field"</span>);</span><br><span class="line"><span class="keyword">object</span>[] attributeArr = fi.GetCustomAttributes(<span class="keyword">typeof</span>(SomeAttribute), <span class="literal">false</span>);</span><br></pre></td></tr></table></figure></p>
<h3 id="限制和注意事项"><a href="#限制和注意事项" class="headerlink" title="限制和注意事项"></a>限制和注意事项</h3><ul>
<li>在Unity主工程中不能通过new T()的方式来创建热更工程中的类型实例</li>
</ul>

    <div class="footer">
        发现错误？想参与编辑？ 
        <a href="https://github.com/Ourpalm/ILRuntime/tree/master/docs/source/src/v1/guide/reflection.md" target="_blank">
            在 Github 上编辑此页！
        </a>
    </div>
</article>

<div class="sub-nav hiden-in-phone">
    <dl id="sub-nav">
        <dt>本文内容</dt>
        <dd v-for="(ele, index) in sub_nav">
           <a v-bind:href="ele.href">{{ ele.name }}</a>
        </dd>
    </dl>
</div> 
</div>

<footer>
    <div>
        <p>© Copyright 2017 Ourpalm All Rights Reserved</p>
        <p>掌趣科技2017</p>
    </div>
</footer>


<script>
var vm = new Vue({
    el : '#container',
    data: {
        sub_nav : [ ]
    },
    created:function(){
        var obj = [];
        $("article h3").each(function(){
            obj.push({name :  $(this).find("a").attr("title") , href : "#"+$(this).attr("id") });
        });

        this.sub_nav = obj;       
    }
});

var isShow = false;
$("nav").on("click","#btn-menu" , function(){

    if(!isShow){
        
        if($(document).scrollTop() > $(".sidebar").height() - 100){

            $('html, body').animate({scrollTop:0} , 300, "swing",function(){

                $(".sidebar").fadeIn();
                $(".container").animate({"left" : "15rem"}, 500,"swing");
            });
        }else{

                $(".sidebar").fadeIn();
                $(".container").animate({"left" : "15rem"}, 500,"swing");

        }

    }else{
        $(".sidebar").fadeOut();
        $(".container").animate({"left" : "0rem"}, 500,"swing");
    }
    isShow = !isShow;

});

$(".container").on("click" , "article" , function(){

    if(isShow){
        $(".sidebar").fadeOut();
        $(".container").animate({"left" : "0rem"}, 500,"swing");
        isShow = false;    
    }

});
</script>
        
    </body>
</html>